/*
 * @Author: mikey.zhaopeng 
 * @Date: 2023-02-14 16:14:34 
 * @Last Modified by:   mikey.zhaopeng 
 * @Last Modified time: 2023-02-14 16:14:34 
 */
#include<iostream>
#include <cstring>
using namespace std;
extern "C"{

    void softmax(float *in, float *out, int size, int dim)
    {
        float* max_v = (float*)malloc(sizeof(float) * size/dim);
        memset(max_v,-128,sizeof(float) * size/dim);
        for (size_t i=0; i<size; ++i) {
            //cout<<in[i]<<" ";
            max_v[i/dim]=max_v[i/dim]>in[i]?max_v[i/dim]:in[i];
        }

        float xLimit = 87, param = 0.6931471805599453;
        float *sumValue = (float*)malloc(sizeof(float) * size/dim);
        memset(sumValue,0.f,sizeof(float) * size/dim);
        for (size_t i=0; i<size; ++i) {
            auto x=in[i]-max_v[i/dim];
            //cout<<i/dim<<" "<<max_v[i/dim]<<endl;
            
            x = x > -xLimit ? x : -xLimit;
            x = x < xLimit ? x : xLimit;

            int div = (x / param);
            int div2 = (div + 127) << 23;

            auto xReamin = x - div * param;
            float expBasic = *(float*)(&div2);

            auto t = xReamin;
            auto expRemain = ((((1.0f / 120 * t + 1.0f / 24) * t + 1.0f / 6) * t + 0.5f) * t + 1.0f) * t + 1.0f;
        
            out[i] = expBasic * expRemain;
            sumValue[i/dim] += out[i];
        }
        
        for (int i = 0; i < size; ++i) {
            out[i] *= 1.f / sumValue[i/dim];
        }

    }
}
